/* -*- mode: c++ -*- */
/**
 * @file   array_one.cpp
 * @author billjeff <http://billjeff.blogbus.com>
 * @date   Dec/6/2007
 * 
 * 
 * This code is based on SVG Lib Board Lib(http://libboard.sf.net).
 * You can use this code under the licence of GPL V3.
 *
 * class svgForArray1 is used for one dimension array in our program.
 * This code is part of project SVG-Container(http://code.google.com/p/svg-container/)
 */


//#include "array_one.h"


namespace SVGCont{
  
  template<typename T>
  void svgForArray1<T>::printStep(){
    b.drawText( sx_, y_-UNITSIZE/2, "Step " ) ;
    sx_ += UNITSIZE ;
    char temp[1024] ;
    b.drawText( sx_, y_-UNITSIZE/2, itoa(c_, temp, 10) ) ;
    sx_ = 0.0 ;
    ++c_ ;
  }
  template<typename T>
  void svgForArray1<T>::drawVal( const char *val ){
    if ( val == 0 || val[0] == 0 )
      return ;
    double adj = 1.5-1.0/(strlen(val)+0.1) ;
    //adj = sqrt(adj) ;
    b.setFontSize( 13.0/adj ) ;
    double x, y ;
    x = lx_+UNITSIZE/10 ;
    y = y_-HEIGHT/2 ;
    b.drawText( x, y, val ) ;
    b.setFontSize( fontsize_ ) ;
  }
  // Draw each rectangle of the array.
  template<typename T>
  void svgForArray1<T>::drawUnit( double &x, double &y, const T &v, bool f ){
    if ( f ){
      b.setFillColorRGBi( 102, 0, 0 ) ;
      b.drawRectangle( x, y, UNITSIZE, UNITSIZE ) ;
      b.setFillColorRGBi( 255, 255, 255 ) ;
    }
    else
      b.drawRectangle( x, y, UNITSIZE, UNITSIZE ) ;
    //transform T and call drawVal ;
    char temp[INFOSIZE] ;
    trans( temp, v ) ;
    drawVal( temp ) ;
    x += UNITSIZE ;
  }
  // Draw the whole array by this function
  template<typename T>
  void svgForArray1<T>::drawLine( double &x, double &y, int n, const T *arr, int px ){
    for ( int i = 0 ; i < n ; ++i ){
      if ( px == i )
	drawUnit( x, y, arr[i], true ) ;
      else
	drawUnit( x, y, arr[i] ) ;
    }
    
    y += HEIGHT ;
    x = 2*UNITSIZE ;
  }
  template<typename T>
  void svgForArray1<T>::drawLine( double &x, double &y, int n, int *arr, int an, const T *aval, bool f ){
    for ( int i = 0 ; i < n ; ++i ){
      bool f = false ;
      for ( int j = 0 ; j < an ; ++j )
	if ( i == arr[j] ){
	  drawUnit( x, y, aval[i], true ) ;	  
	  f = true ;
	  break ;
	}
      if ( !f )
	drawUnit( x, y, aval[i] ) ;
    }
    if ( !f )
      y += HEIGHT ;
    else
      y += UNITSIZE ;
    x = 2*UNITSIZE ;
  }
  template<typename T>
  svgForArray1<T>::svgForArray1( const char * info, int nx )  
    : c_(0), dim_(1), nx_(nx), ny_(0), fontsize_(11.0) {
    sx_ = y_ = 0.0 ;
    lx_ = 2*UNITSIZE ;
      strcpy( info_, info ) ;
  }
  template<typename T>
  void svgForArray1<T>::iniSVG( T const * arr ) { // draw the basic array ;
    //b.drawText( x_, y_, "Ini Array" ) ;
    //y_ += strlen( "Ini" ) ;
    //x_ += UNITSIZE ;
    printStep() ;
    //draw( x_, y_ ) ;				\
    
    if ( dim_ == 1 ){
      drawLine( lx_, y_, nx_, 0, 0, arr ) ;
    }      
  }
  template<typename T>
  void svgForArray1<T>::resizeArray( int len, T const * arr ) { // if resize the array, re-draw svg
    nx_ = len ;
    iniSVG( arr ) ;
    return ;
  }    
  template<typename T>
  void svgForArray1<T>::updateSVG( const T *arr, int n, ... ){
    printStep() ;
    va_list vl ;
    va_start(vl, n) ;
    assert( n >= 0 ) ;
    int pos[n+1] ;
    for ( int i = 0 ; i < n ; ++i )
      pos[i] = va_arg( vl, int ) ;
    va_end(vl) ;
    
    drawLine( lx_, y_, nx_, pos, n, arr ) ;     
    
  }
  template<typename T>
  void svgForArray1<T>::writeSVG( const char *name ){
    b.saveSVG( name, 0.5 ) ;
  }
}

